package dao

import models.Tables._
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import play.api.libs.json.JsValue
import slick.jdbc.JdbcProfile
import tool.Pojo._

import javax.inject.{Inject, Singleton}
import scala.concurrent.ExecutionContext.Implicits.global

/**
 * Created by yz on 2018/7/17
 */
@Singleton
class InterInDelDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends
  HasDatabaseConfigProvider[JdbcProfile] {

  import com.github.tototoshi.slick.MySQLJodaSupport._
  import utils.MyPostgresProfile.api._

  type MyRow = InterIndelRow
  val table = InterIndel

  def insertAll(rows: List[MyRow]) = db.run(table ++= rows).map(_ => ())

  def deleteAll = db.run(table.delete).map(_ => ())

  def selectAll = db.run(table.result)

  def getTrueColumnName(x: String) = {
    val r = "([A-Z])".r
    r.replaceAllIn(x, (matcher) =>
      s"_${matcher.group(1).toLowerCase}"
    )
  }

  def selectAll(map: collection.Map[String, JsValue], pageData: PageData) = {
    val columnTrue = LiteralColumn(true)
    val filterData = table.filter { x =>
      val numMinMap = map.filter(_._1.endsWith("Min"))
      val bs = numMinMap.map { case (k, json) =>
        val columnName = getTrueColumnName(k.replaceAll("Min$", ""))
        val op = json.asOpt[Int]
        op.map { int =>
          x.getIntColumn(columnName) >= int
        }.getOrElse(columnTrue)
      }
      val b = bs.foldLeft(true.bind)((x, y) => x && y)
      b
    }.filter { x =>
      val numMaxMap = map.filter(_._1.endsWith("Max"))
      val bs = numMaxMap.map { case (k, json) =>
        val columnName = getTrueColumnName(k.replaceAll("Max$", ""))
        val op = json.asOpt[Int]
        op.map { int =>
          x.getIntColumn(columnName) <= int
        }.getOrElse(columnTrue)
      }
      val b = bs.foldLeft(true.bind)((x, y) => x && y)
      b
    }.filter { x =>
      val textMap = map.filter(_._1.endsWith("Text"))
      val bs = textMap.map { case (k, json) =>
        val columnName = getTrueColumnName(k.replaceAll("Text", ""))
        val op = json.asOpt[String]
        op.map { v =>
          x.getStrColumn(columnName).like(s"%${v}%")
        }.getOrElse(columnTrue)
      }
      val b = bs.foldLeft(true.bind)((x, y) => x && y)
      b
    }

    val sortData = map.get("sort").map { json =>
      val field = (json \ "field").as[String]
      val kind = (json \ "kind").as[String]
      val order = (json \ "order").as[String]
      val columnName = getTrueColumnName(field)
      if (kind == "int") {
        order match {
          case "asc" => filterData.sortBy { y =>
            y.getIntColumn(columnName)
          }
          case "desc" => filterData.sortBy { x =>
            x.getIntColumn(columnName).desc
          }
        }
      } else {
        order match {
          case "asc" => filterData.sortBy { y =>
            y.getStrColumn(columnName)
          }
          case "desc" => filterData.sortBy { x =>
            x.getStrColumn(columnName).desc
          }
        }
      }
    }.getOrElse(filterData)

    val finalData = sortData
    val countF = finalData.length.result
    val resultF = finalData.drop(pageData.offset).take(pageData.limit).result
    val f = countF.zip(resultF)
    db.run(f)
  }


}
